/*
 * @Description: 鼠标滚轮事件
 * @Author: James324
 * @Date: 2023-09-06 15:05:45
 * @LastEditors: James324
 * @LastEditTime: 2024-03-20 10:42:20
 */
import { TableRefs } from 'element-plus';
import resizeIcon from '../img/resize.svg';
import moveIcon from '../img/move.svg';
import { getCursorIcon, getDom, hasClass, getElCssValue } from '@/utils';
import helpStore from '@/store/modules/helpStore';
import type { BaseTableProps } from '../type';

export function useMouse(props?: BaseTableProps) {
    const tableRef = ref();
    const HelpStore = helpStore();

    let oTable: TableRefs;
    let bodyWrapper: HTMLElement;
    let headerWrapper: HTMLElement;
    let cleardown: any;
    let clearup: any;
    let clearmove: any;
    let clearWindowMouseUp: any;

    onMounted(() => {
        oTable = tableRef.value!.layout.table.refs;

        // 拿到可以滚动的元素
        bodyWrapper = oTable.bodyWrapper.firstElementChild!.firstElementChild as HTMLElement;
        headerWrapper = oTable.headerWrapper;

        /**
         * 监听鼠标事件
         */
        cleardown = useEventListener(headerWrapper, 'mousedown', handleMouseDown);
        clearup = useEventListener(headerWrapper, 'mouseup', handleMouseUp);
        clearmove = useEventListener(
            headerWrapper,
            'mousemove',
            useThrottleFn(handleMove, 60),
            false
        );
        clearWindowMouseUp = useEventListener(window, 'mouseup', handleMouseUp);
    });

    onUnmounted(() => {
        cleardown?.();
        clearup?.();
        clearmove?.();
        clearWindowMouseUp?.();
    });

    /**
     * TODO: 鼠标拖拽事件，待补充
     */
    const mouseFlag = ref(false); // 标记是否处于鼠标移动状态
    const mouseOffset = ref(0);

    // 按下鼠标记录鼠标位置
    const handleMouseDown = (e: MouseEvent) => {
        const target = e.target as HTMLElement;
        const columnRect = target.getBoundingClientRect();

        if (columnRect.right - e.pageX > 8) {
            mouseOffset.value = e.clientX;
            mouseFlag.value = true;
        }
    };

    const handleMouseUp = () => {
        mouseFlag.value = false;
    };

    const snackbarVisible = ref(false);
    const snackbarText = ref('');
    const moveOffset = reactive({ x: '0', y: '0' });
    let tableBodyWidth: number;
    let bodyScrollWidth: number;
    const handleMove = (e: MouseEvent) => {
        const target = e.target as HTMLElement;
        const currentTarget = e.currentTarget as HTMLElement;
        const columnRect = target.getBoundingClientRect();

        // 只获取一次
        if (!tableBodyWidth) {
            tableBodyWidth = getDom('.el-table__body', bodyWrapper)?.offsetWidth as number;
            bodyScrollWidth = tableBodyWidth - bodyWrapper.offsetWidth;
        }

        if (getParents(e.target)) {
            currentTarget.style.cursor = 'default';
            return; // 存在 no-resize 类名，不做任何操作
        }

        // 避免与表格拖拽功能冲突
        if (columnRect.width > 12 && columnRect.right - e.pageX < 8) {
            if (!props?.border || mouseFlag.value) return; // 开启列宽度拖拽或者正在左右拖动时
            mouseFlag.value = false;
            currentTarget.style.cursor = getCursorIcon(resizeIcon);

            if (!HelpStore.snackbarContext.dragGuid) {
                setSnackbarOffset(e);
                setSnackbarVisible('dragGuid', '鼠标长按，可拖拽移动表格列宽');
            }
        } else {
            if (bodyScrollWidth > 0) {
                currentTarget.style.cursor = getCursorIcon(moveIcon);
                if (!HelpStore.snackbarContext.moveGuid) {
                    setSnackbarOffset(e);
                    setSnackbarVisible('moveGuid', '鼠标长按，可使表格左右移动');
                }
            } else {
                currentTarget.style.cursor = 'default';
            }
        }

        if (mouseFlag.value) {
            // 设置水平方向的元素的位置
            const scrollLeft =
                bodyWrapper.scrollLeft - (-mouseOffset.value + (mouseOffset.value = e.clientX));
            tableRef.value!.setScrollLeft(scrollLeft);
        }
    };

    /**
     * 向上获取父节点, 并查找是否存在 no-resize 类名，如果存在终止循环
     */
    const getParents = (elem: any) => {
        let isDisabled = false;
        while (elem.parentNode) {
            if (hasClass(elem, 'no-resize')) {
                isDisabled = true;
                break;
            }
            if (elem.parentNode.tagName === 'TR') break;
            elem = elem.parentNode;
        }
        return isDisabled;
    };

    /**
     * 设置提示消息条状态
     */
    interface SnackbarContext {
        [key: string]: any;
        dragGuid: boolean;
        moveGuid: boolean;
    }

    const setSnackbarVisible = (key: string, text: string) => {
        snackbarVisible.value = true;
        (HelpStore.snackbarContext as SnackbarContext)[key] = true;
        snackbarText.value = text;
    };

    /**
     * 设置提示消息条偏移量
     */
    const snackOverflow = ref(false);
    const setSnackbarOffset = (e: MouseEvent) => {
        const headerRect = headerWrapper.getBoundingClientRect();
        const snackbarDOM = getDom('#snackbar') as HTMLElement;
        const snackbarWidth = parseInt(getElCssValue(snackbarDOM, 'min-width'));
        const totalOffsetX = snackbarWidth + e.pageX;

        snackOverflow.value = totalOffsetX >= window.innerWidth;
        // 判断当前提示是否溢出窗口
        if (snackOverflow.value) {
            moveOffset.x = e.pageX - snackbarWidth + 24 + 'px';
        } else {
            moveOffset.x = e.pageX - 24 + 'px';
        }

        moveOffset.y = headerRect.bottom + 5 + 'px';
    };

    return {
        tableRef,
        snackbarVisible,
        snackbarText,
        snackOverflow,
        moveOffset,
        handleMouseDown,
        handleMouseUp,
        handleMove
    };
}
